package wish.filters;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.htmlparser.Node;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.SimpleNodeIterator;

import wish.model.Record;
import wish.model.TaggerExtractor;
import wish.tagChecker.TagSimilarityChecker;


public class SimilarityFilter implements Filter {

	private TagSimilarityChecker tagSimilarityChecker;

	public SimilarityFilter(TagSimilarityChecker tagChecker){
		
		this.tagSimilarityChecker = tagChecker;
	
		//cluster might work fine.
		
	}
	
	@Override
	public Record filter(Record region) {
		
		List<Node> toRemove = new ArrayList<Node>();
		
		int index = 0;
		
		NodeList nodeList = region.getNodeList();
		
		for (int i = 0; i < nodeList.size()-1; i++) {
			
			Node node1 = nodeList.elementAt(index);
			
			Node node2 = nodeList.elementAt(i+1);
			
			Set<String> firstDistinctTags = getDistinctTags(node1);
			
			Set<String> secondDistinctTags = getDistinctTags(node2);
			
			if (!acceptableDifferenceInTags(firstDistinctTags,secondDistinctTags)){
				
//				System.err.println("removing");
//				
//				System.err.println(node1.toHtml(true));
//				
//				System.err.println("node2");
//				
//				System.err.println(node2.toHtml(true));
				
				toRemove.add(node1);
				
				index = i+1;
				
				continue;
				
			}
			
			Set<String> firstDistinctTagsAllLevel = getDistinctTagsAllLevel(node1);
			
			Set<String> secondDistinctTagsAllLevel = getDistinctTagsAllLevel(node2);
			
			if (!acceptableDifferenceInAllTags(firstDistinctTagsAllLevel,secondDistinctTagsAllLevel)){
				
				toRemove.add(node1);
				
				index = i+1;
				
				continue;
				
			}
		
		}
		
		//removeElements
		
		for (Node node : toRemove) {
			
			nodeList.remove(node);
			
		}
		
		if (region.getNodeList().size() == 0){
			return null;
		}
		
		return region;
		
	}

	private boolean acceptableDifferenceInAllTags(
			Set<String> firstDistinctTagsAllLevel, Set<String> secondDistinctTags) {
		
		return tagSimilarityChecker.acceptAllTags(firstDistinctTagsAllLevel,secondDistinctTags);
		
	}

	private boolean acceptableDifferenceInTags(Set<String> firstDistinctTags,
			Set<String> secondDistinctTags) {
		
		return tagSimilarityChecker.acceptTags(firstDistinctTags,secondDistinctTags);
		
	}

	private Set<String> getDistinctTagsAllLevel(Node node) {
		
		Set<String> set = new HashSet<String>();
		
		set.add(TaggerExtractor.extractTag(node));
		
		if (node.getChildren() == null)
			return set;
		
		SimpleNodeIterator list = node.getChildren().elements();
		
		while (list.hasMoreNodes()){
			
			set.addAll(getDistinctTagsAllLevel(list.nextNode()));
			
		}
		
		return set;
		
	}

	private Set<String> getDistinctTags(Node node) {
		
		Set<String> set = new HashSet<String>();

		if (node.getChildren() == null)
			return set;
		
		SimpleNodeIterator child = node.getChildren().elements();
		
		
		while (child.hasMoreNodes()){
			
			set.add(TaggerExtractor.extractTag(child.nextNode()));
			
		}
		
		return set;
	}

}
